package com.kaixinff.kaixin001.common;


import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

public class Encrypt {
	
	private static int charCodeAt(String str, int index) {
		if (index >= str.length()) {
			return 0;
		}
		return str.charAt(index);
	}
	
	private static int f(int s, int x, int y, int z) {
		switch (s) {
			case 0:
				return (x & y) ^ (~x & z);
			case 1:
				return x ^ y ^ z;
			case 2:
				return (x & y) ^ (x & z) ^ (y & z);
			case 3:
				return x ^ y ^ z;
			default:
				return 0;
		}
	}

	private static int rotl(int x, int n) {
		return (x << n) | (x >>> (32 - n));
	}

	private static String tohs(int str) {
		String s = "";
		int v;
		for ( int i = 7; i >= 0; i--) {
			v = (str >>> (i * 4)) & 0xf;
			s += Integer.toHexString(v);
		}
		return s;
	}

	private static String h(String msg) {
		int[] K = new int[]{0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6};
		msg += (char)0x80;
		int l = msg.length() / 4 + 2;
		int N =  (l + 15) / 16 ;
		int[][] M = new int[N][16];
		for ( int i = 0; i < N; i++) {
			M[i] = new int[16];
			for ( int j = 0; j < 16; j++) {
				M[i][j] = (charCodeAt(msg, i * 64 + j * 4) << 24)
						| (charCodeAt(msg, i * 64 + j * 4 + 1) << 16)
						| (charCodeAt(msg, i * 64 + j * 4 + 2) << 8)
						| (charCodeAt(msg, i * 64 + j * 4 + 3));
			}
		}
		M[N - 1][14] = (int) (((msg.length() - 1) * 8) / 0x100000000L);
		M[N - 1][14] = M[N - 1][14];
		M[N - 1][15] = ((msg.length() - 1) * 8) & 0xffffffff;
		int H0 = 0x67452301;
		int H1 = 0xefcdab89;
		int H2 = 0x98badcfe;
		int H3 = 0x10325476;
		int H4 = 0xc3d2e1f0;
		int[] W = new int[80];
		int a, b, c, d, e;
		for ( int i = 0; i < N; i++) {
			for ( int t = 0; t < 16; t++)
				W[t] = M[i][t];
			for ( int t = 16; t < 80; t++)
				W[t] = rotl(W[t - 3] ^ W[t - 8] ^ W[t - 14]
						^ W[t - 16], 1);
			a = H0;
			b = H1;
			c = H2;
			d = H3;
			e = H4;
			for ( int t = 0; t < 80; t++) {
				int s = t / 20;
				int T = (rotl(a, 5) + f(s, b, c, d) + e
						+ K[s] + W[t]) & 0xffffffff;
				e = d;
				d = c;
				c = rotl(b, 30);
				b = a;
				a = T;
			}
			H0 = (H0 + a) & 0xffffffff;
			H1 = (H1 + b) & 0xffffffff;
			H2 = (H2 + c) & 0xffffffff;
			H3 = (H3 + d) & 0xffffffff;
			H4 = (H4 + e) & 0xffffffff;
		}
		return tohs(H0) + tohs(H1) + tohs(H2)
				+ tohs(H3) + tohs(H4);
	}

	private static String bh(int[] ar) {
		String[] charHex = new String[]{"0", "1", "2", "3", "4", "5", "6", "7",
				"8", "9", "a", "b", "c", "d", "e", "f"};
		String str = "";
		int len = ar.length;
		for ( int i = 0, tmp = len << 2; i < tmp; i++) {
			str += charHex[(int)((ar[i >> 2] >> (((i & 3) << 3) + 4)) & 0xF)]
					+ charHex[(int)((ar[i >> 2] >> ((i & 3) << 3)) & 0xF)];
		}
		return str;
	}

	private static int[] sl(String s, boolean w) {
		int len = s.length();
		int[] v;
		int len2 = (len + 3) / 4;
		if (w) {
			v = new int[len2 + 1];
		} else {
			v = new int[len2];
		}
		for ( int i = 0; i < len; i += 4) {
			v[i >> 2] = charCodeAt(s, i) | charCodeAt(s, i + 1) << 8
					| charCodeAt(s, i + 2) << 16
					| charCodeAt(s, i + 3) << 24;
		}
		if (w) {
			v[v.length - 1] = len;
		}
		return v;
	}

	private static String en(String pwd, String key) {
		if (pwd.equals("")) {
			return "";
		}
		int[] v = sl(pwd, true);
		int[] k = sl(key, false);
		if (k.length < 4) {
			int[] k2 = new int[4];
			System.arraycopy(k, 0, k2, 0, k.length);
			k = k2;
		}
		
		int n = v.length - 1;
		int z = v[n], y = v[0];
//		long de = 2654435769L;
		int de = 0x9E3779B9;
		int mx, e, p, q = 6 + 52 / (n + 1), sum = 0;
		while (0 < q--) {
			sum = sum + de & 0xffffffff;
			e = sum >>> 2 & 3;
			for (p = 0; p < n; p++) {
				y = v[(int) (p + 1)];
				mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4)
						^ (sum ^ y) + (k[(p & 3 ^ e)] ^ z);
				z = v[(int) p] = v[p] + mx & 0xffffffff;
			}
			y = v[0];
			mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y)
					+ (k[(int) (p & 3 ^ e)] ^ z);
			z = v[n] = v[n] + mx & 0xffffffff;
		}
		return bh(v);
	}

	private static String uen(String str) throws UnsupportedEncodingException {
		return URLEncoder.encode(str, "UTF-8").replace("*", "%2A");
	}

	public static String enp(String pwd, String key) throws UnsupportedEncodingException {
		return h(en(uen(pwd), key));
	}
}
